﻿using System.Runtime.CompilerServices;

namespace shape
{
    public abstract class Shape
    {
        public abstract double Area { get; }
        public abstract bool IsValid { get; }
    }

    public class Rectangle : Shape
    {
        public double Length { get; set; }
        public double Width { get; set; }

        public Rectangle(double length, double width)
        {
            Length = length;
            Width = width;
        }
        public override double Area => Length * Width;
        public override bool IsValid => Length > 0 && Width > 0;
    }

    public class Square : Shape
    {
        public double Side { get; set; }

        public Square(double side)
        {
            Side = side;
        }
        public override double Area => Side * Side;
        public override bool IsValid => Side > 0;
    }

    public class Triangle : Shape
    {
        public double A { get; set; }
        public double B { get; set; }
        public double C { get; set; }

        public Triangle(double a, double b, double c)
        {
            A = a; B = b; C = c;
        }
        public override double Area
        {
            get
            {
                if (!IsValid) return 0;
                double p = (A + B + C) / 2;
                return Math.Sqrt(p * (p-A) *(p-B) * (p-C));
            }
        }

        public override bool IsValid
        {
            get
            {
                return A > 0 && B > 0 && C > 0
                    && (A + B) > C && (B + C) > A && (A + C) > B;
            }
        }
    }

    public static class ShapeFactory
    {
        private static Random random = new Random();

        public static Shape CreateRandomShape()
        {
            int shapeType = random.Next(3);
            switch (shapeType)
            {
                case 0:
                    return new Rectangle(random.NextDouble() * 10, random.NextDouble() * 10);
                case 1:
                    return new Square(random.NextDouble() * 10);
                case 2:
                    double sideA = random.NextDouble() * 10;
                    double sideB = random.NextDouble() * 10;
                    double sideC = random.NextDouble() * (sideA + sideB);
                    return new Triangle(sideA, sideB, sideC);
                default:
                    throw new ArgumentException();
            }
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            var rectangle = new Rectangle(10, 20);
            Console.WriteLine($"Rectangle area: {rectangle.Area}");
            Console.WriteLine($"Is rectangle valid: {rectangle.IsValid}");

            var square = new Square(10);
            Console.WriteLine($"Square area: {square.Area}");
            Console.WriteLine($"Is square valid: {square.IsValid}");

            var triangle = new Triangle(3, 4, 5);
            Console.WriteLine($"Triangle area: {triangle.Area}");
            Console.WriteLine($"Is triangle valid: {triangle.IsValid}");

            var shapes = new List<Shape>();
            for ( int i = 0; i < 10; i++)
            {
                shapes.Add(ShapeFactory.CreateRandomShape());
            }
            double totalArea = 0;
            foreach ( Shape shape in shapes )
            {
                totalArea += shape.Area;
            }
            Console.WriteLine($"total area: {totalArea}");
        }
    }
}